package net.sourceforge.ehep.core;

import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.Vector;

import net.sourceforge.ehep.EhepResources;
import net.sourceforge.ehep.gui.HexTable;

public class bufferManager {
	/**Created Sophia- 06/18/09*/
	private int currFileBufSize = 0; 
	//the required minimum length of the file 
	//in order to be watermarked
	private int reqMinLength = 25;
	Vector<String> signVals = new Vector<String>();
	private Vector<String> advSignVals = new Vector<String>();
	EhepResources resource;
	
	/**
	 * constructor
	 */
	public bufferManager(){
		resource = new EhepResources();
	}
	/**
	 * Returns the current buff size of the byte array in FileManager
	 * NOTE: will have to make modifications to take care of Delete, append and 
	 * insert operations (in HexTable Buffer) 
	 * @author Sophia 
	 * Date: 06/18/09
	 */
	public int getCurrFileBufSize(){
		return this.currFileBufSize;
	}

	/**
	 * Returns the current buff size of the byte array in FileManager
	 * NOTE: will have to make modifications to take care of Delete, append and 
	 * insert operations (in HexTable Buffer) 
	 * @author Sophia 
	 * Date: 06/18/09
	 */
	public void setCurrFileBufSize(int size){
		this.currFileBufSize = size;
	}
	
	/**
	 * To find the row in the ArrayList to which this byte index
	 * will belong.
	 * NOTE: will need to change this logic for a more flexible buffer size to 
	 * take care of modifying the buffer dynamically. 
	 * insert operations (in HexTable Buffer) 
	 * @author Sophia 
	 * Date: 06/18/09
	 */
	public int getArrayListRowIndex(int currByteIndex, HexTable table){
		int maxRows = EHEP.BUFFER_SIZE / EHEP.TABLE_NUM_DATA_COLUMNS;
		int rowIndex = (maxRows * currByteIndex) / EHEP.BUFFER_SIZE;
		if(rowIndex < table.getItemCount())
			return rowIndex;
		else
			return -1;
	}
	
	/**
	 * To find the column in the ArrayList to which this byte index
	 * will belong.
	 * NOTE: will need to change this logic for a more flexible buffer size to 
	 * take care of modifying the buffer dynamically. 
	 * insert operations (in HexTable Buffer) 
	 * @author Sophia 
	 * Date: 06/18/09
	 */
	public int getArrayListColIndex(int currByteIndex){
		int colIndex = (currByteIndex % EHEP.TABLE_NUM_DATA_COLUMNS) + 1;
		//TODO: place some check to verify the col index is valid
			return colIndex;
		
	}
	
	/**
	 * Modify buffer to insert a character at the end.
	 * @author Sophia 
	 * Date: 06/20/09
	 */
	public void modifyBufInsCharEnd(String sigChoice){
		byte byteVal = 0;
		if(getCurrFileBufSize() < 1){
			//return -1;
		}
		Vector<String> signatureVals = new Vector<String>();
		parseStringMethod(signatureVals, sigChoice, ",");
		try{
			char charVal = signatureVals.elementAt(0).charAt(0);
			byteVal= (byte)charVal;
		}catch(ArrayIndexOutOfBoundsException ex){
			System.out.println(ex.getMessage());
		}catch(IndexOutOfBoundsException ex){
			System.out.println(ex.getMessage());
		}
		synchronized(FileManager.buffer){
			FileManager.buffer[getCurrFileBufSize() - 1] = byteVal;
		}
		//return signatureVals.size();
	}
	
	/**
	 * Modify buffer to insert a signature at the end.
	 * @author Sophia 
	 * Date: 06/21/09
	 */
	public int modifyBufInsSignEnd(String sigChoice){
		int sigLen, bufLen;
		Vector<String> signatureVals = new Vector<String>();
		parseStringMethod(signatureVals, sigChoice, ",");
		sigLen = signatureVals.size();
		reqMinLength = sigLen + 5;
		bufLen = getCurrFileBufSize();
		if(bufLen < reqMinLength){
			return -2;
		}
		synchronized(FileManager.buffer){
			for(int i=1;i<=sigLen;i++){
				char charVal = signatureVals.elementAt(sigLen - i).charAt(0);
				byte byteVal = (byte)charVal;
				FileManager.buffer[bufLen - i] = byteVal;
			}
		}
		return sigLen;
	}

	/**
	 * Modify buffer to insert a signature at a specified 
	 * location in the buffer.
	 * Note: this method has not been implemented yet in the code.
	 * @author Sophia 
	 * Date: 06/21/09
	 */
	public int modifyBufInsSignAdv(String sigChoice){
		int oldSigSize, bufLen, sigLen, bufIndx;
		StringTokenizer innerStr;
		String sigVal = EhepResources.getMyResource(sigChoice);
		StringTokenizer strToken = new StringTokenizer(sigVal, ",");
		while(strToken.hasMoreTokens()){
			signVals.add(strToken.nextToken());
		}
		//another method
		oldSigSize = signVals.size();
		for(int num = 0; num < oldSigSize; num++){
			innerStr = new StringTokenizer(signVals.elementAt(num), ";");
			while(innerStr.hasMoreTokens()){
				advSignVals.add(innerStr.nextToken());
			}
		}
		
		sigLen = advSignVals.size();
		
		bufLen = getCurrFileBufSize();
		if(bufLen < (sigLen + 70)){
			return -1;
		}
		
		int padding = Integer.parseInt(EhepResources.getMyResource("watermark.pad"));
		bufIndx = 0;
		int num = 0;
		int count = 0;
		int strln = (signVals.elementAt(num++).length() / 2) + 1;
		for(int i=0;i < sigLen;i++){
				if(count< strln){
		   			char charVal = advSignVals.elementAt(i).charAt(0);
		   			byte byteVal = (byte)charVal;
		   			FileManager.buffer[bufIndx++] = byteVal;
		   			count++;
		   		}else{
		   			bufIndx += padding;
		   			count = 0;
		   			if(num<signVals.size()){
		   				strln = ((signVals.elementAt(num++).length() / 2) + 1);
		   			}else{
		   				break;
		   			}
		   		}
		   		
		   	}
		
		return sigLen;
	}
	
	/**
	 * Verifies that a specific character has been inserted at a 
	 * specific location in the buffer (i.e. the file has been 
	 * watermarked).
	 * @author Sophia 
	 * Date: 06/21/09
	 */
	public boolean verifyBufInsCharEnd(String sigChoice){
		char charVal;
		byte byteVal = 0;
		if(getCurrFileBufSize() < 1){
			return false;
		}
		Vector<String> signatureVals = new Vector<String>();
		parseStringMethod(signatureVals, sigChoice, ",");
		try{
			charVal = signatureVals.elementAt(0).charAt(0);
			byteVal= (byte)charVal;
		}catch(ArrayIndexOutOfBoundsException ex){
			System.out.println(ex.getMessage());
		}catch(IndexOutOfBoundsException ex){
			System.out.println(ex.getMessage());
		}
		if(FileManager.buffer[getCurrFileBufSize() - 1] == byteVal){
			return true;
		}else{
			return false;
		}
				
	}
	
	/**
	 * Verifies that a specific signature has been inserted at a 
	 * specific location in the buffer (i.e. the file has been 
	 * watermarked).
	 * @author Sophia 
	 * Date: 06/21/09
	 */
	public boolean verifyBufInsSignEnd(String sigChoice){
		int sigLen, bufLen;
		Vector<String> signatureVals = new Vector<String>();
		parseStringMethod(signatureVals, sigChoice, ",");
		sigLen = signatureVals.size();
		bufLen = getCurrFileBufSize();
		if(bufLen >= sigLen){
			for(int i=1;i<=sigLen;i++){
				char charVal = signatureVals.elementAt(sigLen - i).charAt(0);
				byte byteVal = (byte)charVal;
				if(FileManager.buffer[bufLen - i] != (byteVal)){
					return false;
				}
			}
		}else{
			return false;
		}
		return true;
	}

	/**
	 * Verifies that the file already watermarked with a specific character at a 
	 * specific location. If this is the case then the watermarking is removed from 
	 * those locations.
	 * @author Sophia 
	 * Date: 06/21/09
	 */
	public boolean removeBufCharEnd(String sigChoice){
		if(getCurrFileBufSize() < 1){
			return false;
		}
		if(verifyBufInsCharEnd(sigChoice)){
			String replaceStr = EhepResources.getMyResource("watermark.init");
			char charVal = replaceStr.charAt(0);
			byte byteVal= (byte)charVal;
			synchronized(FileManager.buffer){
				FileManager.buffer[getCurrFileBufSize() - 1] = byteVal;
			}
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * Verifies that the file already watermarked with a specific signature at a 
	 * specific location. If this is the case then the watermarking is removed from 
	 * those locations.
	 * @author Sophia 
	 * Date: 06/21/09
	 */
	public boolean removeBufSignEnd(String sigChoice){
		int sigLen, bufLen;
		Vector<String> signatureVals = new Vector<String>();
		parseStringMethod(signatureVals, sigChoice, ",");
		sigLen = signatureVals.size();
		bufLen = getCurrFileBufSize();
		if(verifyBufInsSignEnd(sigChoice)){
			String replaceStr = EhepResources.getMyResource("watermark.init");
			char replaceChar = replaceStr.charAt(0);
			byte replaceByte = (byte)replaceChar;
			
			synchronized(FileManager.buffer){
				for(int i=1;i<=sigLen;i++){
					FileManager.buffer[bufLen - i] = replaceByte;
				}
			}
			return true;
		}else{
			return false;
		}
	}

	/**
	 * Parse string and add it to the vector.
	 * Note: the string is obtained from the 'EhepResources.properties' file
	 * @author Sophia 
	 * Date: 06/23/09
	 */
	public void parseStringMethod(Vector<String> signatureVals, String sigChoice, String parser){
		String sigVal = EhepResources.getMyResource(sigChoice);
		try{
			StringTokenizer strToken = new StringTokenizer(sigVal, parser);
			while(strToken.hasMoreTokens()){
				signatureVals.add(strToken.nextToken());
			}
		}catch(NullPointerException ex){
			System.out.println(ex.getMessage());
		}catch (NoSuchElementException ex) {
			System.out.println(ex.getMessage());
		}
		
	}
	
}
